package org.xxpay.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.xxpay.core.common.constant.MchConstant;
import org.xxpay.core.common.constant.RetEnum;
import org.xxpay.core.common.exception.ServiceException;
import org.xxpay.core.entity.*;
import org.xxpay.core.service.IMchPayPassageService;
import org.xxpay.service.dao.mapper.*;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

/**
 * @author: dingzhiwei
 * @date: 2018/5/3
 * @description: 商户支付通道
 */
@Service
public class MchPayPassageServiceImpl implements IMchPayPassageService {

    @Autowired
    private MchPayPassageMapper mchPayPassageMapper;

    @Autowired
    private PayPassageMapper payPassageMapper;

    @Autowired
    private PayDivisionMchMapper payDivisionMchMapper;

    @Autowired
    private MchInfoMapper mchInfoMapper;

    @Autowired
    private AgentPassageMapper agentPassageMapper;

    @Override
    public int add(MchPayPassage mchPayPassage) {
        checkDivision(mchPayPassage);
        return mchPayPassageMapper.insertSelective(mchPayPassage);
    }

    @Override
    public int update(MchPayPassage mchPayPassage) {
        checkDivision(mchPayPassage);
        return mchPayPassageMapper.updateByPrimaryKeySelective(mchPayPassage);
    }

    /**
     * 校验分账规则 是否正确
     * @param mchPayPassage
     */
    private void checkDivision(MchPayPassage mchPayPassage){

        List<Integer> payPassageIdList = new ArrayList<>();
        if(mchPayPassage.getIfMode() == 1) { // 单独
            payPassageIdList.add(mchPayPassage.getPayPassageId());
        }else if(mchPayPassage.getIfMode() == 2) { // 轮询
            JSONArray array = JSON.parseArray(mchPayPassage.getPollParam());
            array.stream().forEach(jsonObj -> payPassageIdList.add(((JSONObject) jsonObj).getIntValue("payPassageId")));
        }

        if(payPassageIdList.isEmpty()){ //为选择任何支付通道信息
            throw new ServiceException(RetEnum.RET_COMM_OPERATION_FAIL);
        }

        //查询选中的支付通道中需要分账的通道
        PayPassageExample exa = new PayPassageExample();
        exa.createCriteria().andIdIn(payPassageIdList).andIsDivisionEqualTo(MchConstant.PUB_YES);
        List<PayPassage> canDivisionPayPassageList = payPassageMapper.selectByExample(exa);

        if(canDivisionPayPassageList.isEmpty()){ //不包含需要分账的通道，校验通过
            return ;
        }

        //查询商户，代理商，总代理信息
        Long mchId = mchPayPassage.getMchId();
        MchInfo mchInfo = mchInfoMapper.selectByPrimaryKey(mchId);
        Long agentId = mchInfo.getAgentId();
        Long parentAgentId = mchInfo.getParentAgentId();

        for(PayPassage payPassage : canDivisionPayPassageList){

            //查询商户的上游分账账号配置是否存在
            PayDivisionMchExample divExa = new PayDivisionMchExample();
            divExa.createCriteria().andIfTypeCodeEqualTo(payPassage.getIfTypeCode())
            .andInfoTypeEqualTo(MchConstant.SETT_INFO_TYPE_MCH).andInfoIdEqualTo(mchId);
            if( payDivisionMchMapper.countByExample(divExa) < 1 ){
                throw new ServiceException(RetEnum.RET_MGR_DIVISION_ACCOUNT_NOT_EXISTS);
            }

            //查询商户代理商的上游分账账号配置是否存在
            if(agentId != null){
                divExa = new PayDivisionMchExample();
                divExa.createCriteria().andIfTypeCodeEqualTo(payPassage.getIfTypeCode())
                        .andInfoTypeEqualTo(MchConstant.SETT_INFO_TYPE_AGENT).andInfoIdEqualTo(agentId);
                if( payDivisionMchMapper.countByExample(divExa) < 1 ){
                    throw new ServiceException(RetEnum.RET_MGR_DIVISION_ACCOUNT_NOT_EXISTS);
                }
            }

            //查询总代理商的上游分账账号配置是否存在
            if(parentAgentId != null && parentAgentId != 0) {
                divExa = new PayDivisionMchExample();
                divExa.createCriteria().andIfTypeCodeEqualTo(payPassage.getIfTypeCode())
                        .andInfoTypeEqualTo(MchConstant.SETT_INFO_TYPE_AGENT).andInfoIdEqualTo(parentAgentId);
                if( payDivisionMchMapper.countByExample(divExa) < 1 ){
                    throw new ServiceException(RetEnum.RET_MGR_DIVISION_ACCOUNT_NOT_EXISTS);
                }
            }
        }
    }


    @Override
    public int update(MchPayPassage updateMchPayPassage, MchPayPassage queryMchPayPassage) {
        MchPayPassageExample example = new MchPayPassageExample();
        MchPayPassageExample.Criteria criteria = example.createCriteria();
        setCriteria(criteria, queryMchPayPassage);
        return mchPayPassageMapper.updateByExampleSelective(updateMchPayPassage, example);
    }

    @Override
    public MchPayPassage findById(Integer id) {
        return mchPayPassageMapper.selectByPrimaryKey(id);
    }

    @Override
    public MchPayPassage findByMchIdAndProductId(Long mchId, Integer productId) {
        MchPayPassage mchPayPassage = new MchPayPassage();
        mchPayPassage.setMchId(mchId);
        mchPayPassage.setProductId(productId);
        List<MchPayPassage> mchPayPassageList = selectAll(mchPayPassage);
        if(CollectionUtils.isEmpty(mchPayPassageList)) return null;
        return mchPayPassageList.get(0);
    }

    @Override
    public List<MchPayPassage> select(int offset, int limit, MchPayPassage mchPayPassage) {
        MchPayPassageExample example = new MchPayPassageExample();
        example.setOrderByClause("createTime DESC");
        example.setOffset(offset);
        example.setLimit(limit);
        MchPayPassageExample.Criteria criteria = example.createCriteria();
        setCriteria(criteria, mchPayPassage);
        return mchPayPassageMapper.selectByExample(example);
    }

    @Override
    public Integer count(MchPayPassage mchPayPassage) {
        MchPayPassageExample example = new MchPayPassageExample();
        MchPayPassageExample.Criteria criteria = example.createCriteria();
        setCriteria(criteria, mchPayPassage);
        return mchPayPassageMapper.countByExample(example);
    }

    @Override
    public List<MchPayPassage> selectAll(MchPayPassage mchPayPassage) {
        MchPayPassageExample example = new MchPayPassageExample();
        example.setOrderByClause("createTime DESC");
        MchPayPassageExample.Criteria criteria = example.createCriteria();
        setCriteria(criteria, mchPayPassage);
        return mchPayPassageMapper.selectByExample(example);
    }

    @Override
    public List<MchPayPassage> selectAllByMchId(Long mchId) {
        MchPayPassage mchPayPassage = new MchPayPassage();
        mchPayPassage.setMchId(mchId);
        return selectAll(mchPayPassage);
    }

    @Override
    @Transactional(transactionManager = "transactionManager", rollbackFor = Exception.class)
    public int batchUpdate(String mchIds, MchPayPassage mchPayPassage) {

        //批量设置的商户费率
        BigDecimal batchMchRate = mchPayPassage.getMchRate() != null ? new BigDecimal(mchPayPassage.getMchRate().toString()) : null;

        String[] mchIdArr = mchIds.split(",");
        int count = 0;
        // 遍历商户
        for (String id : mchIdArr) {
            Long mchId = Long.valueOf(id);
            // 商户代理商信息
            MchInfo mchInfo = mchInfoMapper.selectByPrimaryKey(mchId);
            if (mchInfo == null) {
                throw ServiceException.build(RetEnum.RET_SERVICE_MCH_NOT_EXIST);
            }

            //全局设置了费率， 则统一费率， 否则查询当前商户的费率
            if(batchMchRate == null){

                MchPayPassage dbMchPassage = findByMchIdAndProductId(mchId, mchPayPassage.getProductId());
                if(dbMchPassage == null){ //没有设置通道费率 && 该商户没有设置过费率
                    throw ServiceException.build(RetEnum.RET_MCH_PASSAGE_NOT_EXIST);
                }
                mchPayPassage.setMchRate(dbMchPassage.getMchRate()); // 设置原费率
            }

            //如果包含代理商
            if (mchInfo.getAgentId() != null && mchInfo.getAgentId() > 0) {

                // 代理商通道配置
                AgentPassage agentPassage = agentPassageMapper.selectByAgentIdAndProductId(mchInfo.getAgentId(), mchPayPassage.getProductId());
                if (agentPassage == null) {
                    throw ServiceException.build(RetEnum.RET_MGR_MCH_AGENT_PASSAGE_NULL);
                }
                // 判断代理商费率是否大于商户费率
                if (agentPassage.getAgentRate().compareTo(mchPayPassage.getMchRate()) > 0) {
                    throw ServiceException.build(RetEnum.RET_MGR_BATCH_UPDATE_PASSAGE_RATE_ERROR);
                }
            }


            // 删除当前商户产品通道配置
            mchPayPassage.setMchId(mchId);
            mchPayPassageMapper.deleteByMchIdAndProductId(mchId, mchPayPassage.getProductId());
            // 插入通道配置
            if(mchPayPassage.getIfMode() == 1) { // 单独
                mchPayPassage.setPollParam(null);
            }else if(mchPayPassage.getIfMode() == 2) { // 轮询
                mchPayPassage.setPayPassageId(null);
                mchPayPassage.setPayPassageAccountId(null);
            }
            mchPayPassageMapper.insertSelective(mchPayPassage);
            count ++;
        }
        return count;
    }


    void setCriteria(MchPayPassageExample.Criteria criteria, MchPayPassage obj) {
        if(obj != null) {
            if(obj.getMchId() != null) criteria.andMchIdEqualTo(obj.getMchId());
            if(obj.getProductId() != null) criteria.andProductIdEqualTo(obj.getProductId());
            if(obj.getStatus() != null && obj.getStatus().byteValue() != -99) criteria.andStatusEqualTo(obj.getStatus());
        }
    }
}
